-------------------------------------------------------------------------------
-- Title      : PWM for robot servos
-- Project    : 
-------------------------------------------------------------------------------
-- File       : my_pwm.vhd
-- Author     :   <ngunton@ptolome.cems.uwe.ac.uk>
-- Company    : FoCEMS, UWE
-- Last update: 2011-03-28
-- Platform   : Altera Quartus with std_arith library and DE0 board
-------------------------------------------------------------------------------
-- Description: A very simple example of a pwm hardware implementation. It has
-- three processes, one to divide the 50Mhz clock down to ~1khz, an eight bit
-- counter for the full cycle (at 1khz) and a loadable duty cycle register (8
-- bit). Button 0 is the reset, press to start. switches 7 to 0 are the load
-- value for the duty cycle register. Switch 9 is the pwm output enable. The
-- PWM output is connected to LED0 which will range from always on (100% duty)
-- to always off (0% duty). Enjoy.
-- 
-------------------------------------------------------------------------------
-- Revisions  : 0
-- Date        Version  Author  Description
-- 2007/02/07  1.0      ngunton	Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_Arith.all;

entity my_pwm is
  
  port (
    clk          			: in  std_logic;
    duty_cycle_grip  	: in  std_logic_vector(7 downto 0);
 --   duty_cycle_shoulder : in  std_logic_vector(7 downto 0);
 --   duty_cycle_base  	: in  std_logic_vector(7 downto 0);
 --   duty_cycle_elbow	 	: in  std_logic_vector(7 downto 0);
    pwm_enable   			: in  std_logic;
    resetn       			: in  std_logic;
  	 pwm_out_grip 			: out std_logic
--	 pwm_out_shoulder 	: out std_logic;
--	 pwm_out_elbow 		: out std_logic;
--	 pwm_out_base 			: out std_logic
		);

end my_pwm;


architecture behavioural of my_pwm is
signal clock_div : unsigned(15 downto 0);
signal counter : unsigned(7 downto 0);
signal pwm_out_sig, slow_clk : std_logic;
signal duty_cycle_reg_grip : unsigned(7 downto 0);
--signal duty_cycle_reg_base : unsigned(7 downto 0);
--signal duty_cycle_reg_shoulder : unsigned(7 downto 0);
--signal duty_cycle_reg_elbow : unsigned(7 downto 0);
signal duty_cycle_reg : unsigned(7 downto 0);
signal pwm_out_reg_grip : std_logic;
--signal pwm_out_reg_shoulder : std_logic;
--signal pwm_out_reg_elbow : std_logic;
--signal pwm_out_reg_base : std_logic;


begin  -- behavioural

  
  -- purpose: manage the duty cycle register
  -- type   : sequential
  -- inputs : clk, resetn, 
  -- outputs: duty_out_sig
  control: process (clk, resetn, duty_cycle_reg_grip)
  begin  -- process control
    if resetn = '0' then                -- asynchronous reset (active low)
      duty_cycle_reg <= conv_unsigned(X"F0",8);
    else
      if clk'event and clk = '1' then  -- rising clock edge
        duty_cycle_reg_grip  <= unsigned(duty_cycle_grip);
--		  duty_cycle_reg_shoulder <= unsigned(duty_cycle_shoulder);
--		  duty_cycle_reg_base  <= unsigned(duty_cycle_base );
--		  duty_cycle_reg_elbow <= unsigned(duty_cycle_elbow);
      end if;
    end if;
  end process control;

  -- purpose: divide system clock down from 50Mhz to 1khz
  -- type   : sequential
  -- inputs : clk, resetn
  -- outputs: slow_clk
  clockdiv: process (clk, resetn)
  begin  -- process clockdiv
    if resetn = '0' then                -- asynchronous reset (active low)
      slow_clk <= '0';
      clock_div <= X"0000";
    elsif clk'event and clk = '1' then  -- rising clock edge
      if clock_div = conv_unsigned(X"0064",16) then
        clock_div <= conv_unsigned(X"0000",16);
        slow_clk <= not slow_clk;
      else
        clock_div <= clock_div +1;
      end if;
    end if;
  end process clockdiv;

-- purpose: control the pwm_out 
-- type   : sequential
-- inputs : slow_clk, resetn, pwm_enable
-- outputs: pwm_out_sig

  pulse: process (slow_clk, resetn, pwm_enable)
begin  -- process pulse

	
 -- if resetn = '0' then                  -- asynchronous reset (active low)
  --  pwm_out_sig <= '0';    
 -- else
    if slow_clk'event and slow_clk = '1' then    -- rising clock edge
      counter <= counter +1;  
		
		
      if (counter < conv_unsigned(duty_cycle_reg_grip,8)) then
         pwm_out_reg_grip <= '1';
      else
         pwm_out_reg_grip <= '0';
      end if;
--		
--		if (counter < conv_unsigned(duty_cycle_reg_shoulder,8)) then
--         pwm_out_reg_shoulder <= '1';
--      else
--         pwm_out_reg_shoulder <= '0';
--      end if;
--		
--	   if (counter < conv_unsigned(duty_cycle_reg_elbow,8)) then
--         pwm_out_reg_elbow <= '1';
--      else
--         pwm_out_reg_elbow <= '0';
--      end if;
--		
--	   if (counter < conv_unsigned(duty_cycle_reg_base,8)) then
--         pwm_out_reg_base <= '1';
--      else
--         pwm_out_reg_base <= '0';
--      end if;
		
		
    end if;
 -- end if;
end process pulse;

pwm_out_grip <= pwm_out_reg_grip;
--pwm_out_shoulder <= pwm_out_reg_shoulder;
--pwm_out_elbow <= pwm_out_reg_elbow;
--pwm_out_base <= pwm_out_reg_base;

      

end behavioural;
